#include <iostream>
#include <type_traits>

template<typename T>
std::remove_reference_t<T>&& MyMove(T&& t) {
	using ReturnType = std::remove_reference_t<T>;
	return static_cast<ReturnType&&>(t);
}

class MyClass {
public:
	MyClass() {
		std::cout << "MyClass Default Constructor" << std::endl;
	}

	MyClass(const MyClass& mc) {
		std::cout << "MyClass Copy Constructor" << std::endl;
	}

	MyClass(MyClass&& mc) noexcept {
		std::cout << "MyClass Move Constructor" << std::endl;
	}

public:
	int i = 0;
};

class MyWidget {
	MyClass MC;

public:
	MyWidget(const MyClass mc) :
		MC(std::move(mc))
	{
	}
};

void process(const MyClass& widget) {
	std::cout << "deal l value" << std::endl;
}

void process(MyClass&& widget) {
	std::cout << "deal r value" << std::endl;
}

void process(int&& i) {
	std::cout << "deal r int value" << std::endl;
}

void process(const int& i) {
	std::cout << "deal l int value" << std::endl;
}

void LogAndProcess(MyClass&& t) {
	std::cout << "Log: LogAndProcess(): ";

	//process(std::move(t));

	//process(std::forward<MyClass>(t));
	//process(t);

	process(std::forward<int>(t.i));
	process(std::move(t.i));
}

void LogAndProcess(const MyClass& t) {
	std::cout << "Log: LogAndProcess(): ";

	//process(std::forward<const MyClass>(t));
	process(t);
}

template<typename T>
void TLogAndProcess(T&& t) {
	std::cout << "Log: TLogAndProcess(): ";
	process(std::forward<T>(t));
}


int main() {
	/*int&& mi = MyMove(10);

	int i = 0;
	int&& mi1 = MyMove(i);*/


	/*MyClass mc;
	MyClass mc1(mc);
	MyClass mc2(std::move(mc));*/

	/*MyClass mc;
	MyWidget mw(mc);

	const int ci = 0;
	//const int&& mci = std::move(ci);

	const int& rci = std::move(ci);*/

	MyClass mc;
	LogAndProcess(std::move(mc));

	//LogAndProcess(mc);

	//TLogAndProcess(mc);
	//TLogAndProcess(std::move(mc));

	return 0;
}